iT邦幫忙

1

STM32-18 CAN-BUS (上)

  • 分享至 

  • xImage
  •  

前幾篇有介紹過CANBus~透過MCP2515模塊去完成通訊。
這篇會使用STM32當中的CAN-Bus來實現通訊~


與之前介紹Can不同的是在STM32當中將一個bit分為3個區段而已,將傳播段與相位緩衝段1結合。
https://ithelp.ithome.com.tw/upload/images/20220326/20146325iCrgPyrniY.png
https://ithelp.ithome.com.tw/upload/images/20220326/20146325kvpgVsPi6H.jpg
可以看到在STM32當中將Bit僅分為3個區段,而同步區段固定為1Tq ; BS1為0-16TQ ;BS2為0-8TQ,採樣點同樣落在BS1與BS2交界。


計算說明

計算Time Quantum (TQ)

TQ = (BRP+1) x Tpclk

TQ= (15+1) x (1/16) = 0.9375(us) = 937.5(ns)

BPR : 預分頻係數 Tpclk : APB Clock 週期

計算Bit Timing

這時可以知道1個TQ為937.5ns,同時SyncSeg固定為1TQ 後續BS1為4TQ BS2為3TQ:

Bit Timing : TQ timing x (1+BS1+BS2)

937.5ns x 8 = 7500ns

TQ Timing : 上方計算出來1 TQ的時間
BS1 : BS1 的TQ數量 BS2 : BS2的TQ數量

計算Baud Rate

Baud Rate = 1 / Bit Timing
1 / 7500ns x 1000000000 = 133333 bit/s

1000000000是因為ns換為s

採樣點計算

(SyncSeg + BS1 )/ 總TQ數量 *100%

以上方來說即為 5 / 8 x 100% = 62.5%

採樣點在通訊過程最好是落在60~70%,所以在選擇TQ數量時要注意採樣點位置!


傳送與接收

  1. 發送 :
  • 3 個 Tx Buffer (Tx0 Tx1 Tx2)
  • 可設置Buffer優先級,根據優先級決定哪個Buffer優先發送
  1. 接收 :
  • 2 個 FIFO Rx Buffer (RX0 RX1)
  • 每個Rx Buffer當中可以接收3筆資料

FIFO (First In First Out) : 先進先出,在RX Buffer當中可以儲存3筆資料,會按照接收到的訊息順序,讀取最先接收到的訊息。

換個方式說假如今天郵差送了一封信到信箱當中而且信箱大小只能容納3封,那這封信就會變成編號1的信件(CAN_RFR→FMP = 0b01),這時候可以選擇去收信或是晚點收。

馬上收信 : 從信箱當中拿走信(CAN_RFR→RFOM = 1),信箱當中是空的了,這時候信箱會將編號歸0,可以重複這個步驟接收下一封信件。

晚點收信 : 信箱中還是有著一封信,假設又收到一封信但由於剛剛沒有取走第一封,這時候就會改為編號2的信件(CAN_RFR→FMP = 0b10),當累積到第三封信件時(CAN_RFR→FMP = 0b11)信箱已經滿了,所以當第四封信件就會放置在信箱外面(溢出)。

針對信箱滿了的情況下可以分為兩種處理方法:

  1. 新的信件直接覆蓋掉剛剛接收的最後一封信件也就是編號3的信件 (CAN_MCR→RFLM = 0)
  2. 丟棄新信件,保留前面所接收到的3封信(CAN_MCR→RFLM = 1)

CAN 中斷說明

在STM32當中CAN具有4個向量中斷 :

  1. TX Interrupt : 傳送中斷,有3個Tx Buffer (0 1 2)
  • 當Tx Buffer 0 當中為空時,觸發傳送中斷(CAN_TSR→RQCP0 = 1)
  • 當Tx Buffer 1 當中為空時,觸發傳送中斷(CAN_TSR→RQCP1 = 1)
  • 當Tx Buffer 2 當中為空時,觸發傳送中斷(CAN_TSR→RQCP2 = 1)
  1. FIFO0 Interrupt : 接收中斷,有2個Rx Buffer (0 1),每一個Buffer可以儲存3筆資料
  • 當FIFO0接收到一筆訊息,觸發中斷
  • 當FIFO0當中接收滿3訊息時,觸發中斷(CAN_RF0R→FULL0 = 1)
  • 當FIFO0接收滿3訊息時又接收了第4筆,發生溢位觸發中斷(CAN_RF0R→FOVR0 = 1)
  1. FIFO1 Interrupt : 接收中斷,有2個Rx Buffer (0 1),每一個Buffer可以儲存3筆資料
  • 當FIFO1接收到一筆訊息,觸發中斷
  • 當FIFO1當中接收滿3訊息時,觸發中斷(CAN_RF1R→FULL1 = 1)
  • 當FIFO1接收滿3訊息時又接收了第4筆,發生溢位觸發中斷(CAN_RF1R→FOVR1 = 1)
  1. SCE Interrupt (status change error interrupt) : 狀態改變與錯誤中斷
  • 當出現錯誤導致中斷(CAN_ESR) EX: 接收錯誤計數器>127、離線
  • 喚醒節點時
  • 進入睡眠模式時

.IOC設置說明

我使用的板子是L476RG,只具備一個CAN通訊(CAN1)。
https://ithelp.ithome.com.tw/upload/images/20220326/20146325zDRvc7aoKg.png

  • Prescaler : 等於上方計算公式的BPR,影響的是TQ的時間。
    這邊我APB Clock為16 ,Prescaler 設為15
    (15+1) x (1/16) = 0.9375(us) = 937.5(ns)

  • Time Quanta Bit Segment 1 : 傳播段與相位緩衝段1結合,會影響到採樣點的位置

  • Time Quanta Bit Segment 2 : 相位緩衝段2,會影響到採樣點的位置

    以上我設置為4TQ與3TQ,而同步段固定為1TQ共8TQ,所以看以看到下方Time for One Bit 為7500ns (937.5ns x 8 = 7500ns)

  • Baud Rate : 1 / 7500ns x 1000000000 = 133333 bit/s

  • ReSynchronization Jump Width : 重新同步跳轉寬度,用來彌補兩設備間的通訊誤差,可設置範圍0-4TQ。
    https://ithelp.ithome.com.tw/upload/images/20220326/20146325Foe7DH04EC.png
    上方圖為基本模式設定,這邊就都選Disable即可。
    而最後的是工作模式選擇 : 分為正常模式、環回模式、靜默模式等等,因為我手邊只有一塊就先選環回模式來測試。
    https://ithelp.ithome.com.tw/upload/images/20220326/201463256z1weYUx9u.png
    四個中斷向量則是上方說明的四個,根據需要可以開啟對應的中斷。


相關函數

  • 設定CAN接收的Filter
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)
  • 啟動CAN
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)
  • 停止CAN
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan)
  • CAN發送訊息: 將一筆訊息送至Buffer當中,同時會請求傳送
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)
  • 停止傳送請求
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
  • 檢查所選的TxBuffer是否有傳送請求
uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
  • 從RXBuffer獲取接收的訊息
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
  • 檢查指定的RxBuffer內所接收到的訊息數(FIFO = 1 2 3)
uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *hcan, uint32_t RxFifo)
  • CAN中斷處理函數 : 依照狀態調用下方對應接收與傳送回調函數
void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan)
  • Tx Buffer 0 傳送中斷回調函數
__weak void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
  • Tx Buffer 1 傳送中斷回調函數
__weak void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
  • Tx Buffer 2 傳送中斷回調函數
__weak void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
  • Rx Buffer 0 接收中斷回調函數
__weak void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance==CAN1)
	{
		HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&rxheader1,msg);
	}
}
  • Rx Buffer 0 溢出中斷回調函數 : 當接收滿3筆訊息時
__weak void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hcan);

  /* NOTE : This function Should not be modified, when the callback is needed,
            the HAL_CAN_RxFifo0FullCallback could be implemented in the user
            file
   */
}
  • Rx Buffer 1 接收中斷回調函數
__weak void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance==CAN1)
	{
		HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&rxheader1,msg);
	}
}
  • Rx Buffer 1 溢出中斷回調函數 : 當接收滿3筆訊息時
__weak void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hcan);

  /* NOTE : This function Should not be modified, when the callback is needed,
            the HAL_CAN_RxFifo0FullCallback could be implemented in the user
            file
   */
}

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言